// Copyright (c) 2025 Huawei Technologies Co., Ltd.
// openUBMC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Description: 实现kvm客户端http协议的基类
#pragma once

#include <boost/beast/http.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/beast/core/detail/base64.hpp>
#include <boost/system/detail/error_code.hpp>
#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/json.hpp>
#include <boost/beast/version.hpp>
#include "boost/asio/ip/tcp.hpp"

using HttpFailInfo = struct {
    std::string errorCode;
    std::string message;
};

class ClientBaseHttp {
public:
    explicit ClientBaseHttp();
    explicit ClientBaseHttp(boost::string_view uri);
    virtual ~ClientBaseHttp();
    // http协议处理的模板方法，派生类中可以直接调用这个方法实现http请求
    bool Call(boost::string_view host, boost::string_view port, boost::string_view userName, const char* passWord,
        boost::beast::http::verb httpMethod);
    // 在发起Call之前，需要确保调用该函数正确设置uri_
    void SetUri(boost::string_view uri);
    // 获得HTTP调用的结果
    boost::beast::http::status GetCallStatus();
    // 获得HTTP调用失败的响应体信息
    virtual HttpFailInfo GetFailInfo();
    // 重置记录响应的成员变量。
    void ResetHttpCall();
    void SetBody(boost::string_view body);

private:
    boost::beast::http::request<boost::beast::http::string_body> GetRequest(boost::string_view host,
        boost::string_view userName, const char* passWord, boost::beast::http::verb httpMethod);
    void CloseStream(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>& stream);
    boost::json::value GetErrorArray(const boost::json::object& obj, boost::string_view cmpKey);
    void ParseErrorCode(const boost::json::object& errorObj);
    void ParseErrorCodeArray(const boost::json::array& arr);
    void ParseErrorInfo();
    virtual void ParseSuccInfo();
    // 解析响应体的模板方法，其中ParseSuccInfo需要在派生类中实现
    void ParseResponse(const boost::beast::http::response<boost::beast::http::dynamic_body>& res);
    void ResetFailRes();
    char* GetEncodeAuth(boost::string_view userName, const char* passWord);
    virtual void ResetSuccRes();

protected:
    std::string uri_;
    char* body_;
    boost::json::object resObj_;
    // 请求失败常见的error信息有error_code与message，所以放基类
    // 而请求成功，响应体不确定，所以放派生类中声明
    HttpFailInfo failRes_;
    // http请求响应状态，如：200是请求成功
    boost::beast::http::status httpResult_;
};
